package com.qqbot;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @Author wenwu.cai
 * @Date 2019/6/5 15:15
 * @Description 参考文档：https://mp.baomidou.com/guide/
 * 使用自动代码生成后，可能需要修改实体类中的数据字段类型和添加@TableName("表名")注解，或者需要删除其余多余的注解，一般保留两个：@Data和@TableName
 * mybatis-plus分页无效，不能够使用自带的分页方法，为保证以前的代码效果，使用pagehelper-spring-boot-starter分页插件，如果是在新的项目，则可以
 * 自行集成pagehelper分页插件包，若自行集成分页插件包，则需要在配置中开启分页效果，而且使用mybatis-plus插件，分页效果可能不能够满足
 * 因此，可以使用spring boot的分页插件包，然后自行编写分页方法，可以使用mybatis-plus的查询list方法和spring boot分页插件配置。这个需要测试，应该可以
 * 达到想要的分页效果。
 * <p>
 * 使用该代码时，可以先进行了解，可能需要进行相关配置修改，修改后，直接运行main方法，然后在控制台输入模块名称和表名，若一次性需要在同一个模块中根据
 * 多个表生成代码，则需要在处理表名的时候，进行分割处理和代码处理
 * <p>
 * 什么是模块？模块是生成这些文件的根路径，如portrayal模块，表名bd_user_portrayal_tag，则生成结构是在项目指定的跟路径下，生成一个portrayal包，然后
 * 根据相关代码都是存放在这个包中，如果设置setModuleName()模块，则会根据每个模块，在每个模块包下生成dao、entity、service、controller包代码。该格式
 * 不符合我们想要的包结构，所以不需要设置模块，没有设置模块，则代码是生成在我们配置的根目录下，存在的包不会覆盖和重新创建，而是在里面增加。若需要
 * 详细了解，可以参考官网具体配置。
 * <p>
 * 查询条件构造器可以参考：https://mp.baomidou.com/guide/wrapper.html#nested，也可以直接传入一个查询实体。构造器非常强大，可以传入各种条件，
 * 也可以直接传入sql语句。根据自身条件，构建符合自身的条件构造器。
 * <p>
 * 生成的文件名称可以自行定义，第一次使用时，可以先详细了解代码。目前了解只是皮毛，大家一起学习一起进步
 */
public class MybatisPlusCodeGenerator {
    private static final String PROJECT_MODEL_NAME = "";
    private static final String JDBC_URL = "jdbc:mysql://121.36.78.169:3306/qqbot?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&serverTimezone=Asia/Shanghai";
    private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
    private static final String USER_NAME = "root";
    private static final String PASSWORD = "fyq13142410";
    private static final String SRC_JAVA = PROJECT_MODEL_NAME + "/src/main/java";
    private static final String SRC_RESOURCE = PROJECT_MODEL_NAME + "/src/main/resources/mapper/";
    private static final String AUTHOR = "fyq";
    private static final String ROOT_PACKAGE_NAME = "com.qqbot";//包根路径
    private static final String CONTROLLER = "controller";//控制层
    private static final String SERVICE = "service";//实现层
    private static final String DAO = "dao";//dao层
    private static final String MODEL = "model";//实体层
    private static final String TABLE_NAME_PREFIX = "demo_";//表名前缀

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + SRC_JAVA);
        gc.setAuthor(AUTHOR);
        gc.setOpen(false);
        //gc.setBaseColumnList(true);
        //gc.setBaseResultMap(true);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        // 自定义文件命名，注意 %s 会自动填充表实体属性！
        gc.setControllerName("%sController");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        //gc.setEntityName("%sEntity");
        gc.setMapperName("%sDao");
        //gc.setXmlName("%sMapper");

        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(JDBC_URL);
        dsc.setDriverName(DRIVER_NAME);
        dsc.setUsername(USER_NAME);
        dsc.setPassword(PASSWORD);
        mpg.setDataSource(dsc);
        // 包配置
        PackageConfig pc = new PackageConfig();
        //模块路径生成，上级包，如果配置这个，则一个模块下都会自动生成controller、service、dao、entity路径
        String modelName = scanner("模块名");
        //pc.setModuleName(modelName);
        pc.setParent(ROOT_PACKAGE_NAME);
        //controller包路径生成
        pc.setController(CONTROLLER + "." + modelName);
        //服务接口层路径生成
        pc.setService(SERVICE + "." + modelName);
        //服务实现层路径生成
        pc.setServiceImpl(SERVICE + "." + modelName);
        //dao层接口路径生成
        pc.setMapper(DAO + "." + modelName);
        //实体类路径生成
        pc.setEntity(MODEL + "." + modelName);
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        /**
         * 注入自定义配置
         */
        // 注入自定义配置，可以在 VM 中使用 cfg.abc 设置的值
        /*InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };*/

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！pc.getModuleName()
                return projectPath + SRC_RESOURCE + modelName
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录");
                return false;
            }
        });
        */

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出代码模板模板
        String tableName = scanner("表名");
        //指定自定义模板路径，注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        /*templateConfig.setEntity();
        templateConfig.setService();
        templateConfig.setMapper();
        templateConfig.setController();*/
        /**
         * 模板配置
         */
        /*mpg.setTemplate(
                // 关闭默认 xml 生成，调整生成 至 根目录
                new TemplateConfig().setXml(null)
                // 自定义模板配置，模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy
                // 至您项目 src/main/resources/template 目录下，模板名称也可自定义如下配置：
                // .setController("...");
                // .setEntity("...");
                // .setMapper("...");
                // .setXml("...");
                // .setService("...");
                // .setServiceImpl("...");
        );*/

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setTablePrefix(TABLE_NAME_PREFIX);
        strategy.setInclude(tableName);
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntitySerialVersionUID(true);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setEntityBuilderModel(true);
        //父级实体
        //strategy.setSuperEntityClass("com.xiaomalixing.mybatis.plus.entity");
        //strategy.setSuperControllerClass("com.xiaomalixing.mybatis.plus.controller");
        //strategy.setSuperEntityColumns("id");
        //strategy.setControllerMappingHyphenStyle(true);
        // Boolean类型字段是否移除is前缀处理
        // strategy.setEntityBooleanColumnRemoveIsPrefix(true)
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }


}
